package cn.yz.service.impl;
import cn.yz.dto.MenuDto;
import cn.yz.entity.Menu;
import cn.yz.entity.RoleMenu;
import cn.yz.exception.BusinessException;
import cn.yz.mapper.MenuMapper;
import cn.yz.mapper.RoleMenuMapper;
import cn.yz.service.MenuService;
import cn.yz.util.SecurityUserUtil;
import cn.yz.vo.MenuVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;

/**
 * 菜单服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MenuServiceImpl implements MenuService {

    private final MenuMapper menuMapper;

    private final RoleMenuMapper roleMenuMapper;

    @Override
    public List<MenuVo> getUserMenus(String userId) {
        return buildMenuTree(menuMapper.selectUserMenus(userId));
    }

    @Override
    public List<MenuVo> getMenuTree() {
        return buildMenuTree(menuMapper.selectMenuTree());
    }

    @Override
    public MenuVo getMenuById(String id) {
        MenuVo menu = menuMapper.selectMenuById(id);
        if (menu == null) {
            throw new BusinessException("菜单不存在");
        }
        return menu;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createMenu(MenuDto menuDto) {
        Menu menu = new Menu();

        BeanUtils.copyProperties(menuDto, menu);
        menuMapper.insert(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMenu(String id, MenuDto menuDto) {
        Menu existingMenu = menuMapper.selectById(id);
        if (existingMenu == null) {
            throw new BusinessException("菜单不存在");
        }

        Menu menu = new Menu();
        BeanUtils.copyProperties(menuDto, menu);
        menu.setId(id);
        menuMapper.updateById(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMenu(String id) {
        Menu menu = menuMapper.selectById(id);
        if (menu == null) {
            throw new BusinessException("菜单不存在");
        }

        // 检查是否有子菜单
        List<MenuVo> children = menuMapper.selectChildrenMenus(id);
        if (!CollectionUtils.isEmpty(children)) {
            throw new BusinessException("存在子菜单，无法删除");
        }

        menuMapper.deleteById(id);
    }

    @Override
    public List<MenuVo> getRoleMenus(String roleId) {
        List<MenuVo> menus = menuMapper.selectRoleMenus(roleId);
        return filterNoButtonTree(buildMenuTree(menus));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignRoleMenus(String roleId, List<String> menuIds) {
        // 删除原有角色菜单关联
        roleMenuMapper.deleteByRoleId(roleId);

        // 添加新的角色菜单关联
        if (!CollectionUtils.isEmpty(menuIds)) {
            List<RoleMenu> roleMenus = menuIds.stream().map(menuId -> {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setId(IdWorker.getIdStr());
                roleMenu.setRoleId(roleId);
                roleMenu.setMenuId(menuId);
                roleMenu.setCreateBy(SecurityUserUtil.getCurrentUsername());
                roleMenu.setUpdateBy(SecurityUserUtil.getCurrentUsername());
                return roleMenu;
            }).collect(Collectors.toList());
            roleMenuMapper.insertBatch(roleMenus);
        }
    }

    @Override
    public List<MenuVo> getMenuTreeNoButton() {
        List<MenuVo> allMenus = menuMapper.selectMenuTree();
        // 递归过滤type=3
        return filterNoButtonTree(buildMenuTree(allMenus));
    }

    /**
     * 构建菜单树
     */
    private List<MenuVo> buildMenuTree(List<MenuVo> menus) {
        if (CollectionUtils.isEmpty(menus)) {
            return new ArrayList<>();
        }

        // 按父ID分组
        Map<String, List<MenuVo>> parentMap = menus.stream()
                .collect(Collectors.groupingBy(menu -> 
                    StringUtils.isBlank(menu.getParentId()) ? "0" : menu.getParentId()));

        // 递归构建树
        return buildTreeRecursive("0", parentMap);
    }

    /**
     * 递归构建菜单树
     */
    private List<MenuVo> buildTreeRecursive(String parentId, Map<String, List<MenuVo>> parentMap) {
        List<MenuVo> children = parentMap.get(parentId);
        if (CollectionUtils.isEmpty(children)) {
            return new ArrayList<>();
        }

        for (MenuVo menu : children) {
            List<MenuVo> childList = buildTreeRecursive(menu.getId(), parentMap);
            if (!CollectionUtils.isEmpty(childList)) {
                menu.setChildren(childList);
            }
        }

        return children;
    }

    /**
     * 递归过滤type=3的菜单
     */
    private List<MenuVo> filterNoButtonTree(List<MenuVo> menus) {
        if (menus == null) return null;
        List<MenuVo> result = new ArrayList<>();
        for (MenuVo menu : menus) {
            if (menu.getType() != null && menu.getType() == 3) continue;
            MenuVo copy = new MenuVo();
            BeanUtils.copyProperties(menu, copy);
            if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
                List<MenuVo> filteredChildren = filterNoButtonTree(menu.getChildren());
                copy.setChildren(filteredChildren);
            }
            result.add(copy);
        }
        return result;
    }
} 